package com.gengine.resource.core
{
	import com.gengine.resource.loader.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.utils.*;
	
	public class StreamLoader extends EventDispatcher
	{
		private var _url:String;
		private var _urlLoader:URLLoader;
		private var _contentType:String;
		private var _loaderInfo:LoaderInfo;
		
		public function StreamLoader()
		{

		}
		
		public function load(url:String) : void
		{
			this._url = url;
			this.initLoader();
		}
		
		public function initLoader() : void
		{
			this._urlLoader = new URLLoader();
			this._urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			this._urlLoader.addEventListener(Event.COMPLETE, this.onCompleteHandler);
			this._urlLoader.addEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
			this._urlLoader.addEventListener(IOErrorEvent.IO_ERROR, this.onIOError);
			this._urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onIOError);
			this._urlLoader.load(new URLRequest(this._url));
		}
		
		private function onCompleteHandler(event:Event) : void
		{
			var event:* = event;
			this._urlLoader.removeEventListener(Event.COMPLETE, this.onCompleteHandler);
			this._urlLoader.removeEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
			this._urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, this.onIOError);
			this._urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onIOError);
			try
			{
				this._urlLoader.close();
			}
			catch (e:Error)
			{
			}
			this.initialize(event.target.data);
			this._urlLoader = null;
		}
		
		protected function onProgressHandler(event:ProgressEvent) : void
		{
			dispatchEvent(event);
		}
		
		private function onIOError(event:ErrorEvent) : void
		{
			this._urlLoader.removeEventListener(Event.COMPLETE, this.onCompleteHandler);
			this._urlLoader.removeEventListener(ProgressEvent.PROGRESS, this.onProgressHandler);
			this._urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, this.onIOError);
			this._urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onIOError);
			this.onIOErrorHandler(event);
		}
		
		protected function onIOErrorHandler(event:ErrorEvent) : void
		{
			trace(event.text);
			dispatchEvent(new LoaderErrorEvent(event.text));
		}
		
		public function initialize(bytes:*) : void
		{
			if (!(bytes is ByteArray))
			{
				throw new Error("Default Resource can only process ByteArrays!");
			}
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.onLoadComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.onChangeIOErrorHandler);
			loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onChangeIOErrorHandler);
			loader.loadBytes(bytes);
		}
		
		protected function onContentReady(param:*) : Boolean
		{
			return true;
		}
		
		private function onLoadComplete(event:Event) : void
		{
			var loaderInfo:LoaderInfo = event.target as LoaderInfo;
			this._loaderInfo = loaderInfo;
			loaderInfo.removeEventListener(Event.COMPLETE, this.onLoadComplete);
			loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.onChangeIOErrorHandler);
			loaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onChangeIOErrorHandler);
			if (this.onContentReady(event ? event.target.content : null))
			{
				this.onLoadCompleteHandler();
			}
		}
		
		protected function onLoadCompleteHandler() : void
		{
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function onChangeIOErrorHandler(event:IOErrorEvent) : void
		{
			var loaderInfo:LoaderInfo = event.target as LoaderInfo;
			loaderInfo.removeEventListener(Event.COMPLETE, this.onLoadComplete);
			loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.onChangeIOErrorHandler);
			loaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onChangeIOErrorHandler);
			this.onIOErrorHandler(event);
		}
		
		public function dispose() : void
		{
			this._url = null;
			this._loaderInfo = null;
		}
		
		public function get url() : String
		{
			return this._url;
		}
		
		public function get contentType() : String
		{
			if (this._loaderInfo)
			{
				return this._loaderInfo.contentType;
			}
			return null;
		}
		
		public function get loaderInfo() : LoaderInfo
		{
			return this._loaderInfo;
		}
	}
}
